package com.crawler.clent;

import java.util.List;
import java.util.Map;

import org.apache.commons.codec.binary.Base64;
import org.apache.http.Header;
import org.apache.http.NameValuePair;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;

import com.core.entity.Condition;
import com.core.utils.ConditionDb;
import com.core.utils.ModelDb;
import com.crawler.entity.JdAccount;
import com.crawler.entity.JdOrder;
import com.crawler.parser.ParserKit;
import com.crawler.pojo.Constant;
import com.crawler.pojo.CrawlerSeed;
import com.crawler.pojo.Operate;
import com.crawler.pojo.PageType;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.jfinal.kit.StrKit;

public class JDCrawler extends CrawlerAdapter {
	
	public JDCrawler() {
		if(getClient() == null){
			try {
				initClient(null);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	@Override
	public Map<String, Object> start(CrawlerSeed crawlerSeed) {
		Map<String,Object> map = Maps.newHashMap();
		switch (crawlerSeed.getOp()) {
			case login:
				map = login(crawlerSeed);
				break;
			case fetch:
				map = fetch(crawlerSeed);
				break;
			case destory:
				stop(crawlerSeed);
				break;
			default:
				map = login(crawlerSeed);
				break;
			}
		return map;
	}

	private Map<String, Object> login(CrawlerSeed crawlerSeed) {
		
		setLoginName(crawlerSeed.getUsername());
		setPassword(crawlerSeed.getPassword());
		setPageTypeLoginName(getLoginName());
		
		Map<String,Object> map = Maps.newHashMap();
		if(crawlerSeed.getCheckCode() == null){
			String html = requestGet(PageType.PAGE_FIRSTLOGIN.getUrl(), null);
			cachePage.put(PageType.PAGE_FIRSTLOGIN, html);
			String url = ParserKit.parseText(PageType.PAGE_FIRSTLOGIN, html);
			//获取验证码 需要的 请求头
			HttpPost httpPost = new HttpPost(url+"&yys="+System.currentTimeMillis());
			List<Header> headers = Lists.newArrayList();
			headers.add(new BasicHeader("Host", "authcode.jd.com"));
			headers.add(new BasicHeader("Referer", "https://passport.jd.com/new/login.aspx?ReturnUrl=http%3A%2F%2Fwww.jd.com%2F"));
			headers.add(new BasicHeader("Accept", "image/png,image/*;q=0.8,*/*;q=0.5"));
			headers.add(new BasicHeader("Accept-Language", "zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3"));
			headers.add(new BasicHeader("Accept-Encoding", "gzip, deflate"));
			headers.add(new BasicHeader("Connection", "keep-alive"));
			httpPost.setHeaders(headers.toArray(new Header[0]));
			
			byte[] b = getByteArray(requestProcessor(getClient(), httpPost),httpPost.getURI().toString());
			String imgBase64 = Base64.encodeBase64String(b);
			map.put(Constant.OPERATE, Operate.needCheckCode.getValue());
			map.put(Constant.checkCodeImg, imgBase64);
		}else{
			String html = cachePage.get(PageType.PAGE_FIRSTLOGIN);
			Map<String, Object> token = ParserKit.parseMap(PageType.PAGE_FIRSTLOGIN, html);
			String uuid = token.get("uuid").toString();
			String iname = token.get("iname").toString();
			String ivalue = token.get("ivalue").toString();
			
			List<NameValuePair> params = Lists.newArrayList();
			params.add(new BasicNameValuePair("loginname", crawlerSeed.getUsername()));
			params.add(new BasicNameValuePair("nloginpwd", crawlerSeed.getPassword()));
			params.add(new BasicNameValuePair("loginpwd", crawlerSeed.getPassword()));
			params.add(new BasicNameValuePair("authcode", crawlerSeed.getCheckCode()));
			params.add(new BasicNameValuePair(iname, ivalue));
			params.add(new BasicNameValuePair("uuid", uuid));
			params.add(new BasicNameValuePair("machineNet", ""));
			params.add(new BasicNameValuePair("machineCpu", ""));
			params.add(new BasicNameValuePair("machineDisk", ""));
			
			List<Header> headers = Lists.newArrayList();
			headers.add(new BasicHeader("Host", "passport.jd.com"));
			headers.add(new BasicHeader("Referer", "https://passport.jd.com/uc/login"));
			headers.add(new BasicHeader("x-requestted-with", "XMLHttpRequest"));
			headers.add(new BasicHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8"));
			headers.add(new BasicHeader("Accept", "	*/*"));
			headers.add(new BasicHeader("Accept-Language", "zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3"));
			
			String url = "https://passport.jd.com/uc/loginService?uuid="+uuid+"&ReturnUrl=http%3A%2F%2Fwww.jd.com%2F&r=0.0085306752843185";
			html = requestPost(url, params, headers);
			System.err.println(html);
			if(html.contains("success")){
				map.put(Constant.OPERATE, Operate.fetch.getValue());
				setLoginName(crawlerSeed.getUsername());
				setPassword(crawlerSeed.getPassword());
			}else{
				if(html.contains("username")){
					map.put(Constant.ERROR, "账户名不存在，请重新输入");
				}
				if(html.contains("pwd")){
					map.put(Constant.ERROR, "账户名与密码不匹配，请重新输入");
				}
				if(html.contains("emptyAuthcode")){
					map.put(Constant.ERROR, "验证码不正确或验证码已过期");
				}
			}
		}
		return map;
	}
	
	private void setPageTypeLoginName(String loginName) {
		for (PageType type : PageType.values()) {
			type.setLoginName(getLoginName());
		}
	}

	private Map<String, Object> fetch(CrawlerSeed crawlerSeed) {
		Map<String,Object> map = Maps.newHashMap();
		//订单分页
		List<String> orderPages = Lists.newArrayList();
		String firstPage = requestPost(PageType.PAGE_ORDER.getUrl(), null, null);
		orderPages.add(firstPage);
		String nextPageUrl = ParserKit.parseText(PageType.PAGE_ORDER, firstPage);
		String nextPage = null;
		while (true) {
			if(StrKit.notBlank(nextPageUrl)){
				nextPage = requestPost(nextPageUrl, null, null);
				nextPageUrl = ParserKit.parseText(PageType.PAGE_ORDER, nextPage);
				orderPages.add(nextPage);
			}else{
				break;
			}
		}
		
		//解析用户信息
		String userInfoHtml = requestGet(PageType.PAGE_USERINFO.getUrl(), null);
		Map<String,Object> userInfo = ParserKit.parseMap(PageType.PAGE_USERINFO, userInfoHtml);
		userInfo.put("loginName", getLoginName());
		
		//解析订单
		List<Map<String,Object>> orderList = Lists.newArrayList();
		for (String orderPage : orderPages) {
			orderList.addAll(ParserKit.parseListMap(PageType.PAGE_ORDER, orderPage));
		}
		
		//解析订单收货地址 & 封装完整的订单
		List<Map<String,Object>> orderDetialList = Lists.newArrayList();
		for (Map<String, Object> orderMap : orderList) {
			String addressHtml = requestGet(orderMap.get("orderAddress").toString(), null);
			String orderAddress = ParserKit.parseText(PageType.PAGE_ORDERDETIAL,orderMap.get("orderStatus").toString(), addressHtml);
			orderMap.put("orderAddress", orderAddress);
			orderMap.put("loginName", getLoginName());
			orderMap.put("customerID", userInfo.get("customerID"));
			orderDetialList.add(orderMap);
		}
	
		//清空同一个customerID的数据
		clearDataByCustomerID(userInfo.get("customerID").toString().trim());
		
		//保存数据
		ModelDb.save(JdAccount.class, userInfo);
		ModelDb.batchSave(JdOrder.class, orderDetialList);		
	
		//登出
		logout();
		map.put(Constant.OPERATE, getLoginName()+"抓取完成！");
		CrawlerManager.remove(getLoginName());
		return map;
	}

	private void clearDataByCustomerID(String customerID) {
		Condition condition = Condition.parseCondition("customerID_string_eq");
		condition.setValue(customerID);
		ConditionDb.delete(JdAccount.class, condition);
		ConditionDb.delete(JdOrder.class, condition);
	}

	private void logout() {
		requestGet(PageType.PAGE_LOGOUT.getUrl(), null);
	}

	@Override
	public Map<String, Object> stop(CrawlerSeed crawlerSeed) {
		logout();
		CrawlerManager.remove(crawlerSeed.getUsername());
		return null;
	}

}
